// 类型递归操作
namespace RecursionSpace {
	// 做一个实现深层嵌套的promise，并获取它最内层值
	type DeepPromiseValueType<T extends Promise<unknown>> = T extends Promise<
		infer I
	>
		? I extends Promise<unknown>
			? DeepPromiseValueType<I>
			: I
		: never;

	// 以上代码不可以简化, 简化的代码真妙
	type DeepPromiseValueType2<T> = T extends Promise<infer K>
		? DeepPromiseValueType2<K>
		: T;

	type TestPromiseValueType = DeepPromiseValueType<
		Promise<Promise<Promise<Promise<{ name: string; age: number }>>>>
	>;

	type TestPromiseValueType2 = DeepPromiseValueType2<
		Promise<Promise<Promise<Promise<{ name: string; age: number }>>>>
	>;

	// 对数组的操作;
	// 对类型为数组的类型做反转

	type ReverseArr<T> = T extends [infer First, ...infer Rest]
		? [...ReverseArr<Rest>, First]
		: T;

	type TestReverseArr = ReverseArr<[1, 2, 3]>; // [5,4,3,2,1]

	// 判断类型数组中是否有对应的类型存在，若存在返回true,否则返回为 false

	type IsEqual<A, B> = (A extends B ? true : false) &
		(B extends A ? true : false);

	type IncludeArr<T extends Array<unknown>, E> = T extends [
		infer First,
		...infer R,
	]
		? IsEqual<E, First> extends true
			? true
			: IncludeArr<R, E>
		: false;

	type TestIncludeArr = IncludeArr<[1, 2, 4, 5, 6], 5>;

	// 把数组中重复的元素删除掉
	// 1，Result 可以设置一个默认值，这样在使用的时候不用传值
	// 2， Result 相当一个全局变量，在后续逻辑中使用
	// 3， Result 做为变量存放每次执行的数据

	type RemoveArrItem<
		A extends unknown[],
		T,
		Result extends unknown[] = [],
	> = A extends [infer First, ...infer Rest]
		? IsEqual<T, First> extends true
			? RemoveArrItem<Rest, T, Result>
			: RemoveArrItem<Rest, T, [...Result, First]>
		: Result;

	type TestRemoveItem = RemoveArrItem<[1, 2, 2, 3, 4, 5, 3, 2], 2>; // 希望得到 [1,3]

	// 实现初始化固定长度的数组，初始化元组
	type BuildArr<
		N extends number,
		Ele = unknown,
		Result extends unknown[] = [],
	> = Result["length"] extends N
		? Result
		: BuildArr<N, Ele, [...Result, unknown]>;

	type TestBuildArr = BuildArr<3>; // [unknown, unknown, unknown]

	// 写一个类型，实现把字符串中出现的特定符号全部替换
	type ReplaceAll<
		S extends string,
		Prefix extends string,
		ReChar extends string,
	> = S extends `${infer Left}${Prefix}${infer Right}`
		? `${Left}${ReChar}${ReplaceAll<Right, Prefix, ReChar>}`
		: S;

	type TestReplaceAll = ReplaceAll<"zhang_yuan_yuan", "_", "$">; // zhang$yuan$yuan

	type TestReplaceAll2 = ReplaceAll<"zhang_yuan_yuan", "_", "#">; // zhang#yuan#yuan

	// 写一个工具类型，把字符串变成单个的字符用 | 分开
	//TODO: 我的做法，这样会在开头多个 "" 答案还是不对，目前没有解决
	type StringToUnion<
		T extends string,
		Result extends string = "",
		Flag extends string = "",
	> = T extends `${infer First}${infer Other}`
		? StringToUnion<Other, Result | First>
		: Result;

	// 这个是正解
	type StringToUnion2<T extends string> =
		T extends `${infer First}${infer Other}`
			? First | StringToUnion2<Other>
			: never;

	type TestStringToUnion = StringToUnion<"yuan">; // 'y' | 'u' | 'a' | 'n'

	type TestStringToUnion2 = StringToUnion2<"test">; // 'y' | 'u' | 'a' | 'n'

	//TODO: 能不实现把一个数组中的所有元素转成用 |  来连接呢

	type ArrayToUnion<Arr extends unknown[]> = Arr extends [
		infer First,
		...infer Others,
	]
		? First | ArrayToUnion<Others>
		: never;

	type TestArrayToUnion = ArrayToUnion<["zhang", "san", "li", "sisi"]>; // 'zhang' | 'san' | 'li' | 'sisi'

	// 实现把字符串中出现的反转

	type ReverseStr<T extends string> = T extends `${infer First}${infer End}`
		? `${ReverseStr<End>}${First}`
		: "";

	type TestReverseStr = ReverseStr<"yuan">; // 转成这样的: nauy

	// 还可以这样写

	type ReverseStr2<
		T extends string,
		Result extends string = "",
	> = T extends `${infer First}${infer Others}`
		? ReverseStr2<Others, `${First}${Result}`>
		: Result;

	type TestReverseStr2 = ReverseStr2<"yuan">; // 转成这样的: nauy

	// 把object 比较多层，我也不知道有多少层，每层都加上 readonly

	type obj = {
		a: {
			b: {
				c: {
					f: () => "dong";
					d: {
						e: {
							guang: string;
						};
					};
				};
			};
		};
	};

	type ObjToReadonly<T extends Record<string, unknown>> = {
		readonly [Key in keyof T]: T[Key] extends object
			? T[Key] extends Function
				? T[Key]
				: T[Key] extends Record<string, unknown>
					? ObjToReadonly<T[Key]>
					: T[Key]
			: T[Key];
	};

	// 添加一下立刻计算得到相应的类型
	type ObjToReadonly2<T extends Record<string, unknown>> = T extends any
		? {
				readonly [Key in keyof T]: T[Key] extends object
					? T[Key] extends Function
						? T[Key]
						: T[Key] extends Record<string, unknown>
							? ObjToReadonly2<T[Key]>
							: T[Key]
					: T[Key];
			}
		: never;

	type TestObjToReadonly = ObjToReadonly<obj>; // 这里并没有被计算， 所以并不是每个字段类型都显示出加上了readonly

	type TestObjToReadonly2 = ObjToReadonly2<{
		a: { b: { c: { f: () => "abc" } } };
	}>;

	type MM<T> = T extends Record<string, any> ? true : false;
	type MM1<T> = T extends object ? true : false;

	type TestAbc = MM<{}>; // true

	type TestAbc2 = MM1<() => void>; // true; 也就是讲， 函数类型是对象
}
